﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Zero.UControl.Component
{
    /// <summary>
    /// SearchTextBox.xaml 的交互逻辑
    /// </summary>
    public partial class SearchTextBox : UserControl, INotifyPropertyChanged
    {
        public SearchTextBox()
        {
            InitializeComponent();

            PART_Text.PreviewKeyDown += PART_Text_PreviewKeyDown;
            PART_Text.PreviewMouseLeftButtonUp += PART_Text_PreviewMouseLeftButtonUp;
            PART_ListBox.PreviewKeyDown += PART_ListBox_PreviewKeyDown;
            PART_ListBox.PreviewMouseLeftButtonUp += PART_ListBox_PreviewMouseLeftButtonUp;

            Loaded += SearchTextBox_Loaded;
            Unloaded += SearchTextBox_Unloaded;
        }


        #region 普通属性
        private bool _isPopupOpen;
        public bool IsPopupOpen
        {
            get => _isPopupOpen;
            set
            {
                _isPopupOpen = value;
                OnPropertyChanged(nameof(IsPopupOpen));
            }
        }

        public ObservableCollection<string> FilteredSuggestions { get; set; } = new ObservableCollection<string>();
        #endregion

        #region 依赖属性
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(SearchTextBox), new PropertyMetadata("", OnTextChanged));

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var tBox = d as SearchTextBox;
            tBox.UpdateSuggestions();
        }

        public ObservableCollection<string> Suggestions
        {
            get => (ObservableCollection<string>)GetValue(SuggestionsProperty);
            set => SetValue(SuggestionsProperty, value);
        }

        public static readonly DependencyProperty SuggestionsProperty =
          DependencyProperty.Register("Suggestions", typeof(ObservableCollection<string>), typeof(SearchTextBox),
              new PropertyMetadata(null, OnSuggestionChanged));

        private static void OnSuggestionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var tBox = d as SearchTextBox;
            tBox.UpdateSuggestions();
        }


        #endregion

        #region 依赖事件
        public static readonly RoutedEvent DoSearchEvent = EventManager.RegisterRoutedEvent(
            nameof(DoSearch),
            RoutingStrategy.Bubble,
            typeof(RoutedEventHandler),
            typeof(SearchTextBox));

        public event RoutedEventHandler DoSearch
        {
            add => AddHandler(DoSearchEvent, value);
            remove => RemoveHandler(DoSearchEvent, value);
        }
        #endregion

        #region 本地事件
        private void SearchTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            var window = Window.GetWindow(this);
            window.MouseDown += OnWindowMouseDown;
            window.LocationChanged += Window_LocationChanged;
        }

        private void SearchTextBox_Unloaded(object sender, RoutedEventArgs e)
        {
            var window = Window.GetWindow(this);
            window.MouseDown -= OnWindowMouseDown;
            window.LocationChanged -= Window_LocationChanged;
        }

        private void Window_LocationChanged(object? sender, EventArgs e)
        {
            if (PART_Popup.IsOpen)
            {
                var offset = PART_Popup.HorizontalOffset;
                PART_Popup.HorizontalOffset = offset + 1;
                PART_Popup.HorizontalOffset = offset;
            }
        }

        // 点击位置判断，当点击到非控件所在的区域时就要关闭控件
        private void OnWindowMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!IsPopupOpen)
                return;

            // 获取当前点击的元素
            var clickedElement = Mouse.DirectlyOver as DependencyObject;

            if (!IsDescendantOfThisControl(clickedElement))
            {
                IsPopupOpen = false;
            }
        }

        // 判断元素是否是当前控件的子元素
        private bool IsDescendantOfThisControl(DependencyObject element)
        {
            while (element != null)
            {
                if (element == this)
                    return true;
                element = VisualTreeHelper.GetParent(element);
            }
            return false;
        }

        private void Root_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                RaiseEvent(new RoutedEventArgs(DoSearchEvent, this));
            }
        }

        private void Search_Button_Click(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(DoSearchEvent, this));
        }

        private void PART_Text_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (!FilteredSuggestions.Any())
                return;
            if (e.Key == Key.Down)
            {
                if (!PART_ListBox.IsKeyboardFocusWithin)
                {
                    PART_ListBox.Focus();
                    PART_ListBox.SelectedIndex = 0;
                }
                
                e.Handled = true;
            }
            else if (e.Key == Key.Escape)
            {
                if (IsPopupOpen)
                {
                    IsPopupOpen = false;
                    e.Handled = true;
                }
            }
        }

        private void PART_Text_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            FilteredSuggestions.Clear();
            foreach (var sug in Suggestions)
            {
                FilteredSuggestions.Add(sug);
            }
            IsPopupOpen = true;
        }

        private void PART_ListBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                if(PART_ListBox.IsKeyboardFocusWithin && PART_ListBox.SelectedItem is string selectedStr)
                {
                    SetValue(TextProperty, selectedStr);
                    IsPopupOpen = false;
                    PART_Text.CaretIndex = Text.Length;
                    PART_Text.Focus();
                }
            }
            else if(e.Key == Key.Escape)
            {
                if (IsPopupOpen)
                {
                    IsPopupOpen = false;
                    PART_Text.CaretIndex = Text.Length;
                    PART_Text.Focus();
                }
            }
        }

        private void PART_ListBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if(PART_ListBox.SelectedItem is string selectedStr)
            {
                SetValue(TextProperty, selectedStr);
                PART_Text.CaretIndex = selectedStr.Length;
                IsPopupOpen = false;
            }
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        protected void OnPropertyChanged(string prop) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
        #endregion

        #region 本地方法
        private void UpdateSuggestions()
        {
            FilteredSuggestions.Clear();
            if (string.IsNullOrEmpty(Text) || Suggestions == null || Suggestions.Count == 0) return;
            foreach (var sug in Suggestions.Where(s => s.StartsWith(Text, StringComparison.OrdinalIgnoreCase)))
            {
                FilteredSuggestions.Add(sug);
            }

            IsPopupOpen = FilteredSuggestions.Any();
        }

        #endregion
    }
}
